﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TasksUI
{
    public partial class Main : Form
    {
        public Main()
        {
            InitializeComponent();
            notifyIcon = new NotifyIcon(components);
            notifyIcon.Click += new EventHandler(notifyIcon_Click);
            _t = new System.Threading.Timer(delegate(object state)
            {
                if (Tag != null)
                {
                    Tag = null;
                    DoAutoSave();
                }
            }, null, 5 * 60 * 1000, 5 * 60 * 1000);
            _tl = _dao.CreateNewLibrary();

            tccTL.Class = TasksModel.TaskClass.ImportantUrgent;// color
            tccTR.Class = TasksModel.TaskClass.ImportantNotUrgent;
            tccBL.Class = TasksModel.TaskClass.UnimportantUrgent;
            tccBR.Class = TasksModel.TaskClass.UnimportantNotUrgent;

            tccTL.TaskList = tlcTL;
            tccTR.TaskList = tlcTR;
            tccBL.TaskList = tlcBL;
            tccBR.TaskList = tlcBR;

            AttachLibrary(_tl);
            _asm.AutoSave += new EventHandler(_dao_AutoSave);

            new ReflectionIT.UserSettings.IsolatedUserSettings(ProductName).
                RegisterForm("Main", this);
        }

        private void AttachLibrary(TasksModel.TaskLibrary tl)
        {
            tccTL.Library = tl;
            tlcTL.TaskList = tl.Tasks.ImportantUrgentTasks;// refresh

            tccTR.Library = tl;
            tlcTR.TaskList = tl.Tasks.ImportantNotUrgentTasks;

            tccBL.Library = tl;
            tlcBL.TaskList = tl.Tasks.UnimportantUrgentTasks;

            tccBR.Library = tl;
            tlcBR.TaskList = tl.Tasks.UnimportantNotUrgentTasks;

            tl.PropertyChanged += new PropertyChangedEventHandler(tl_PropertyChanged);

            _asm.Attach(tl);
        }

        private void DoAutoSave()
        {
            // invoked every 5 minutes if change marker was set
            // save library in last known localization
            if (_lastFileName != null)
                _dao.SaveLibrary(_lastFileName, _tl, this);
        }

        private void _dao_AutoSave(object sender, EventArgs e)
        {
            Tag = 1;// mark change pending for timer
            _tl.ChangedAt = DateTime.UtcNow;

            bool refr = false;
            if (e is PropertyChangedEventArgs)
            {
                string p = ((PropertyChangedEventArgs)e).PropertyName;
                refr = p == "Priority" || p == "DueDate" || p == "EstimatedEffort" || p == "FinishedAt" ||
                    p == "Status" || p == "Type";
            }
            else
                if (e is System.Collections.Specialized.NotifyCollectionChangedEventArgs)
                    refr = ((System.Collections.Specialized.NotifyCollectionChangedEventArgs)e).Action ==
                        System.Collections.Specialized.NotifyCollectionChangedAction.Add ||
                        ((System.Collections.Specialized.NotifyCollectionChangedEventArgs)e).Action ==
                        System.Collections.Specialized.NotifyCollectionChangedAction.Remove;
            if (refr)
                RefreshDueTasks();
        }

        private void RefreshDueTasks()
        {
            List<TasksModel.Task> due = _tl.GetDueTasks(DateTime.UtcNow);
            TasksModel.TaskLibrary.SortByDue(due);
            stlDueTasks.TaskList = due;
        }

        private TasksUI.Data.TaskDAO _dao = new TasksUI.Data.TaskDAO();
        private TasksModel.AutosaveManager _asm = new TasksModel.AutosaveManager();
        private TasksModel.TaskLibrary _tl;
        private System.Threading.Timer _t;
        private NotifyIcon notifyIcon;

        public TasksModel.AutosaveManager AsM
        {
            get { return _asm; }
        }

        private void tl_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (Tag != null) return;// sentinel
            if (e.PropertyName == "Notes")
            {
                rtbNotes.Rtf = _tl.Notes;
            }
        }

        private void rtbNotes_TextChanged(object sender, EventArgs e)
        {
            Tag = this;
            _tl.Notes = rtbNotes.Rtf;
            Tag = null;
        }

        private void tstbSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue != 13)
                return;
            string find = tstbSearch.Text.Trim();
            if (!string.IsNullOrEmpty(find))
            {
                List<TasksModel.Task> t = _tl.Tasks.SearchByName(find, false);
                if (t.Count == 0)
                {
                    MessageBox.Show(this, "No tasks found.", "Search");
                    return;
                }
                // show results
                using (Form f = new SearchResults(t))
                {
                    f.ShowDialog(this);
                }
            }
        }

        private void tsbOpen_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog d = new OpenFileDialog())
            {
                d.AddExtension = true;
                d.AutoUpgradeEnabled = true;
                d.CheckFileExists = true;
                d.CheckPathExists = true;
                d.DefaultExt = "task";
                d.DereferenceLinks = true;
                d.Filter = "Tasks (*.task)|*.task";
                d.Multiselect = false;
                d.ReadOnlyChecked = false;
                d.RestoreDirectory = true;
                d.ShowReadOnly = false;
                d.Title = "Select task library to open";
                d.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
                if (d.ShowDialog(this) == DialogResult.OK)
                {
                    TasksModel.TaskLibrary tl = _dao.OpenLibrary(d.FileName);
                    AttachLibrary(tl);// to controls and events

                    _tl.PropertyChanged -= new PropertyChangedEventHandler(tl_PropertyChanged);
                    _asm.Detach(_tl);// from events
                    _tl = tl;
                    _lastFileName = d.FileName;

                    tsbSynchronize.Enabled = _tl.SynchSettings != null && _tl.SynchSettings.IsConfigured;
                    tsbOpenWs.Enabled = _tl.SynchSettings is TasksModel.WebServiceSynchSettings;

                    RefreshDueTasks();
                }
            }
        }

        private void tsbSave_Click(object sender, EventArgs e)
        {
            if (!_tl.ChangedAt.HasValue)
                _tl.ChangedAt = DateTime.UtcNow;
            if (_lastFileName == null)
                tsbSaveAs_Click(sender, e);
            else
                _dao.SaveLibrary(_lastFileName, _tl, this);
        }

        private void tsbSaveAs_Click(object sender, EventArgs e)
        {
            using (SaveFileDialog d = new SaveFileDialog())
            {
                d.OverwritePrompt = true;
                d.AddExtension = true;
                d.AutoUpgradeEnabled = true;
                d.CheckFileExists = false;
                d.CheckPathExists = true;
                d.DefaultExt = "task";
                d.DereferenceLinks = true;
                d.Filter = "Tasks (*.task)|*.task";
                d.RestoreDirectory = true;
                d.Title = "Select task library to save";
                d.InitialDirectory = System.IO.Directory.GetCurrentDirectory();
                if (d.ShowDialog(this) == DialogResult.OK)
                {
                    Tag = null;// turn off next autosave
                    if (!_tl.ChangedAt.HasValue)
                        _tl.ChangedAt = DateTime.UtcNow;
                    _dao.SaveLibrary(d.FileName, _tl, this);
                    _lastFileName = d.FileName;
                }
            }
        }

        private string _lastFileName;

        private void tsbCopy_Click(object sender, EventArgs e)
        {
            // TODO this is a temporary shortcut
            TasksUI.Helpers.GoogleHelper g = new TasksUI.Helpers.GoogleHelper();
            g.UseSSL = true;
            g.Connect("login", "pass");
            _tl.SynchSettings.Mode = TasksModel.SynchSettings.SynchDirection.FromExternalOnly;
            g.Synchronize(_tl, false, null);
            
            //TasksModel.Task t = _tl.Tasks.ImportantUrgentTasks[0];
            //Google.GData.Calendar.EventEntry ev= g.AddTask(
            //    t, ((TasksModel.GoogleCalendarSynchSettings)_tl.SynchSettings).Calendar);
            //ev.Title.Text = "test 2";
            //ev.Update();
        }

        public void Archive(TasksModel.Task task)
        {
            task.Archived = true;
            _tl.Tasks.Archived.Append(task);
        }

        public void FromArchive(TasksModel.Task task)
        {
            task.Archived = false;
            _tl.Tasks[task.Class].Append(task);
        }

        private void tstbArchive_Click(object sender, EventArgs e)
        {
            using (Form f = new TaskArchive(_tl.Tasks.Archived))
            {
                f.ShowDialog(this);
            }
        }

        private void Main_FormClosed(object sender, FormClosedEventArgs e)
        {
            _tl.PropertyChanged -= new PropertyChangedEventHandler(tl_PropertyChanged);
            _asm.AutoSave -= new EventHandler(_dao_AutoSave);
            _asm.Detach(_tl);
        }

        private void Main_Resize(object sender, EventArgs e)
        {
            if (Visible && WindowState == FormWindowState.Minimized)
            {
                // minimize to tray
                Hide();
                notifyIcon.Icon = TasksUI.Properties.Resources.Main;
                notifyIcon.BalloonTipText =
                    string.Format("{0} tasks active", _tl.CountActiveTasks(DateTime.UtcNow));
                notifyIcon.ShowBalloonTip(2);
                notifyIcon.Text = this.Text;
                notifyIcon.Visible = true;
                ShowInTaskbar = false;
            }
            if (notifyIcon.Visible && WindowState == FormWindowState.Normal)
            {
                // restoring
                if (!Focused)
                    Activate();
                ShowInTaskbar = true;
                notifyIcon.Visible = false;
            }
        }

        private void notifyIcon_Click(object sender, EventArgs e)
        {
            if (e is MouseEventArgs && ((MouseEventArgs)e).Button != System.Windows.Forms.MouseButtons.Left)
                return;
            if (WindowState == FormWindowState.Minimized)
            {
                // restore
                if (!Visible)
                    Show();
                if (!Focused)
                    Activate();
                WindowState = FormWindowState.Normal;
            }
        }

        private void Main_FormClosing(object sender, System.Windows.Forms.FormClosingEventArgs e)
        {
            if (!e.Cancel)
                notifyIcon.Visible = false;
        }

        public void EditTask(TasksModel.Task task)
        {
            TaskDetails.EditTask(this, _tl, task);
        }

        public void ViewTask(TasksModel.Task task)
        {
            TaskDetails.ViewTask(this, _tl, task);
        }

        private void tsbGoogleSync_Click(object sender, EventArgs e)
        {
            if (_tl.SynchSettings == null)
            {
                SyncConfig.Show(_tl);
            }
            if (_tl.SynchSettings is TasksModel.WebServiceSynchSettings)
                WsSyncConfig.Show(_tl);
            else
                if (_tl.SynchSettings is TasksModel.GoogleCalendarSynchSettings)
                    GoogleSyncConfig.Show(_tl);
            tsbSynchronize.Enabled = _tl.SynchSettings != null && _tl.SynchSettings.IsConfigured;
            tsbOpenWs.Enabled = _tl.SynchSettings is TasksModel.WebServiceSynchSettings;
        }

        private void tsbSynchronize_Click(object sender, EventArgs e)
        {
            if (_tl.SynchSettings == null)
                return;
            Synchronize.Show(_tl);
        }

        private void tsOpenWs_Click(object sender, EventArgs e)
        {
            if (_tl.SynchSettings is TasksModel.WebServiceSynchSettings)
            {
                TasksModel.TaskLibrary tl = OpenFromServer.Show(_tl);
                if (tl != null)
                {
                    AttachLibrary(tl);// to controls and events

                    _tl.PropertyChanged -= new PropertyChangedEventHandler(tl_PropertyChanged);
                    _asm.Detach(_tl);// from events
                    _tl = tl;
                    _lastFileName = null;

                    tsbSynchronize.Enabled = _tl.SynchSettings.IsConfigured;
                    tsbOpenWs.Enabled = _tl.SynchSettings is TasksModel.WebServiceSynchSettings;
                }
            }
        }

        private void tsbAuthors_Click(object sender, EventArgs e)
        {
            Authors.Show(_tl);
        }

        private void tsbFlags_Click(object sender, EventArgs e)
        {
            Flags.Show(_tl);
        }

        private void tsbStatuses_Click(object sender, EventArgs e)
        {
            Statuses.Show(_tl);
        }

        private void tsbFind_Click(object sender, EventArgs e)
        {
            FindTask.Show(_tl);
        }
    }
}